package br.com.supermercado.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;

import br.com.supermercado.domain.Compra;
import br.com.supermercado.domain.Produto;

@Name("compraDAO")
@AutoCreate
public class CompraDAO {

	@In
	private Session hibernateSession;

	public Compra create(Compra compra) {
		hibernateSession.persist(compra);

		return compra;

	}

	public List<Compra> findUltimasCompras(int maximo, Produto produto) {
		if (produto == null) {
			return null;

		}

		Criteria criteria = hibernateSession.createCriteria(Compra.class);

		criteria.add(Restrictions.eq("produto.id", produto.getId()));

		criteria.addOrder(Order.asc("preco"));

		if (maximo > 0) {
			criteria.setMaxResults(maximo);

		}

		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		List<Compra> out = criteria.list();

		return out;

	}

	public List<Compra> findByNomeProdutoAndDataCompra(String nomeProduto, Date data) {
		if (nomeProduto == null && data == null) {
			return null;

		}

		Criteria criteria = hibernateSession.createCriteria(Compra.class);

		if (!"".equals(nomeProduto)) {
			Criteria produtoCriteria = criteria.createCriteria("produto");
			produtoCriteria.add(Restrictions.ilike("descricao", nomeProduto, MatchMode.ANYWHERE));

		}

		if (data != null) {
			criteria.add(Restrictions.eq("data", data));

		}

		criteria.addOrder(Order.asc("data"));
		criteria.addOrder(Order.asc("preco"));

		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		List<Compra> out = criteria.list();

		return out;

	}

	public Compra update(Compra compra) {
		this.hibernateSession.merge(compra);

		return compra;

	}

	public void delete(Compra compra) {
		this.hibernateSession.delete(compra);

	}

	public List<Compra> findMaisBaratas() {
		/*
		SELECT MIN( c.preco ) AS 'MAIS BARATO', c.id_produto, p.descricao AS produto, s.descricao AS supermercado
		FROM compras c
		INNER JOIN supermercados s ON ( c.id_supermercado = s.id )
		INNER JOIN produtos p ON ( c.id_produto = p.id )
		GROUP BY c.id_produto
		ORDER BY c.id_produto, c.preco
		 */

		Criteria criteria = hibernateSession.createCriteria(Compra.class);
		criteria.createAlias("produto", "produto");

		criteria.addOrder(Order.asc("preco"));
		criteria.addOrder(Order.asc("produto.descricao"));
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("id"));
		projectionList.add(Projections.groupProperty("produto.id"));
		projectionList.add(Projections.min("preco"));

		criteria.setProjection(projectionList);

		List out = criteria.list();

		Iterator iter = out.iterator();
		if (!iter.hasNext()) {
			return null;

		}

		List<Compra> comprasBaratasList = new ArrayList<Compra>();

		while (iter.hasNext()) {
			Object[] obj = (Object[]) iter.next();
			comprasBaratasList.add(load((Integer) obj[0]));

		}

		return comprasBaratasList;

	}

	public Compra load(int id) {
		return (Compra) hibernateSession.get(Compra.class, id);
		
	}

}
